package com.qyer.search.model;

import static com.qyer.commons.utils.CommonUtils.cast2Int;
import static com.qyer.commons.utils.CommonUtils.cast2String;
import static com.qyer.search.enums.SearchError.INVALID_PARAMETER;
import static com.qyer.search.model.PageInfo.buildPageInfo;
import static com.qyer.search.model.User.buildUser;
import static org.apache.commons.lang3.builder.ToStringStyle.SHORT_PREFIX_STYLE;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.collect.Sets;
import com.qyer.commons.utils.CommonUtils;
import com.qyer.search.Constants;
import com.qyer.search.cache.mutable.MutableCaches;
import com.qyer.search.exception.InvalidParameterException;
import com.qyer.search.model.aggregation.AggregationRegular;
import com.qyer.search.model.mutable.MarketingInfoForPlace;
import com.qyer.search.model.mutable.MarketingListInfo;
import com.qyer.search.model.mutable.PreferDestination;
import com.qyer.search.model.mutable.PreferKey;
import com.qyer.search.servlet.AbstractServlet;
import com.qyer.search.threading.PreferCache;
import com.qyer.search.utils.SplitStringUtils;
import com.qyer.words.model.Word;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Created by tangzheng on 16/6/13.
 */
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class SearchParameterEntity extends SearchParameterOrigin {
  @JsonProperty
  private String topic;
  @JsonProperty
  private int poiid;
  @JsonProperty
  private int start_city_id;
  @JsonProperty
  private int travel_day;
  @JsonProperty
  private Set<Integer> topicids;
  @JsonProperty
  private Map<String, Object> all_conditions;
  @JsonProperty
  private String continent;

  private static final Set<String> LOG_PARAM = Sets
    .newHashSet("kw", "type1", "type2", "country_id", "city_id", "uid", "guid", "context",
                "source_place", "supplier_id", "topic_id", "s_type", "s_type_group", "dest",
                "destCountry", "poi_id", "start_city", "travel_day");

  public SearchParameterEntity() {
    this.context = "inner-test";
    this.requestId = CommonUtils.getRequestId();
  }
  public SearchParameterEntity(HttpServletRequest req, HttpServletResponse resp, AbstractServlet abstractServlet) throws Exception{

    this.requestId = CommonUtils.getRequestId();
    this.conditions = null;
    this.context = cast2String(req.getParameter("context"));

    this.type1 = StringUtils.trimToNull(req.getParameter("s_type_group"));
    this.type2 = StringUtils.trimToNull(req.getParameter("s_type"));
    try {
      type1s = SplitStringUtils.splitToSet(type1, Constants.SEPARATOR_PARAMETER);
      type2s = SplitStringUtils.splitToSet(type2, Constants.SEPARATOR_PARAMETER);

      this.destinationCountryId = cast2Int(req.getParameter("country_id"));
      this.destinationCityId = cast2Int(req.getParameter("city_id"));
      this.continentId = cast2Int(req.getParameter("continent_id"));
      this.userInputKW = cast2String(req.getParameter("kw"));
      this.destination = cast2String(req.getParameter("dest"));
      this.destCountry = cast2String(req.getParameter("destCountry"));
      this.topic = cast2String(req.getParameter("topic_id"));
      this.start_city_id = cast2Int(req.getParameter("start_city"), -1);
      this.travel_day = cast2Int(req.getParameter("travel_day"), -1);
      this.poiid = cast2Int(req.getParameter("poi_id"), -1);
      this.topicids = SplitStringUtils.splitToSet(this.topic, Constants.SEPARATOR_PARAMETER);
      String setOutString = cast2String(req.getParameter("source_place"));
      this.setOutPlaceId = -1;
      if (StringUtils.isNotBlank(setOutString)) {
        setOutString = setOutString.trim();
        this.setOutPlaceId = Integer.MAX_VALUE;
        if (Constants.START_POS_MAP.containsKey(setOutString))
          setOutPlaceId = Constants.START_POS_MAP.get(setOutString);
      }

      this.supplierId = cast2Int(req.getParameter("supplier_id"));

      if (StringUtils.isNotBlank(this.userInputKW)) {
        this.userInputKW = this.userInputKW.toLowerCase();
      }

      this.user = buildUser(req);
      this.pageInfo = buildPageInfo(req);

      //目的地转换
      Map<Integer, String> cityMap = MutableCaches.getInstance().INVERSE_CITIES.getCacheContent();
      Map<Integer, String> countryMap = MutableCaches.getInstance().INVERSE_COUNTRIES.getCacheContent();
      Map<Integer, Integer> cityCountryIDMap = MutableCaches.getInstance().CITY_COUNTRY_ID_MAP.getCacheContent();
      if(destinationCityId != 0){
        if(!cityMap.containsKey(destinationCityId)){
          throw new InvalidParameterException("非法城市ID:"+destinationCityId);
        }
        if(destinationCountryId == 0){
          if(cityCountryIDMap.containsKey(destinationCityId)){
            destinationCountryId = cityCountryIDMap.get(destinationCityId);
          }else {
            throw new InvalidParameterException("找不到该城市的国家名称");
          }
        }else {
          int id = cityCountryIDMap.get(destinationCityId);
          if(id != destinationCountryId){
            throw new InvalidParameterException("城市国家不匹配");
          }
          if(!countryMap.containsKey(id)){
            throw new InvalidParameterException("国家名字居然不存在!");
          }
        }
        this.destination = cityMap.get(destinationCityId);
        //System.out.println("destination city transfer <1----1> " + this.destination);
        this.destCountry = countryMap.get(destinationCountryId);
        //System.out.println("destination country transfer <2----2> " + this.destCountry);
      }else {
        if(destinationCountryId != 0){
          if(countryMap.containsKey(destinationCountryId)){
            this.destCountry = countryMap.get(this.destinationCountryId);
            //System.out.println("destination country transfer <----> " + this.destCountry);
          }else {
            throw new InvalidParameterException("找不到国家名字");
          }
        }
      }

      //

      all_conditions = new HashMap<>();
      Map parameterMap = req.getParameterMap();
      if (MapUtils.isEmpty(parameterMap)) {
        this.conditions = Collections.emptyMap();
      } else {
        this.conditions = new HashMap<>(10);
        Set<Map.Entry> s = parameterMap.entrySet();
        String k;
        Object valueObject;
        for (Map.Entry entry : s) {
          k = entry.getKey().toString().toLowerCase();

          valueObject = entry.getValue();
          if (valueObject == null) {
            continue;
          }
          /////////////////////////////
          if (valueObject.getClass().isArray()) {
            Object[] objArr = (Object[]) valueObject;
            if (objArr != null && objArr.length == 1) {
              all_conditions.put(k, String.valueOf(objArr[0]));
            } else {
              all_conditions.put(k, objArr);
            }
          } else {
            all_conditions.put(k, String.valueOf(valueObject));
          }
          //////////////////////////////
          if (!LOG_PARAM.contains(k)) {
            if (valueObject.getClass().isArray()) {
              Object[] objArr = (Object[]) valueObject;
              if (objArr != null && objArr.length == 1) {
                conditions.put(k, String.valueOf(objArr[0]));
              } else {
                conditions.put(k, objArr);
              }
            } else {
              conditions.put(k, String.valueOf(valueObject));
            }
          }
        }
      }
    }catch (Exception e){
      abstractServlet.writeError(requestId, context, conditions, resp, System.currentTimeMillis(), INVALID_PARAMETER, e);
      throw e;
    }
    if(!isNullParameter2()){
      //fix
      this.type2 = "145,157";
      this.type2s.add(145);
      this.type2s.add(157);
      //this.type2s.add(2410);
      //this.type2s.add(1785);
    }
  }
  /*public int getConditionCacheKey() {
    int result = type1;
    result = 31 * result + type2;
    result = 31 * result + destinationCountryId;
    result = 31 * result + destinationCityId;
    result = 31 * result + setOutPlaceId;
    result = 31 * result + supplierId;
    return result;
  }*/

  public boolean isOnlyCategory(){
    if(StringUtils.isBlank(type2) && StringUtils.isBlank(userInputKW)
      && (destinationCountryId ==0) && (destinationCityId == 0) && (setOutPlaceId == -1)
      && (supplierId == 0) && (StringUtils.isBlank(this.destination)) && (StringUtils.isEmpty(
      this.destCountry)) && (StringUtils.isEmpty(this.continent)) && (StringUtils.isEmpty(this.topic))
      && (this.poiid == -1) && (this.start_city_id == -1) && (this.travel_day == -1)){
      if(this.type1s.size() == 1)
        return true;
    }
    return false;
  }

  public boolean isVStypeOK(int channel) throws Exception{
    Set<Integer> s_type_set = MutableCaches.getInstance().Z_TAG_SNAPSHOT.getCacheContent()
                                                                        .getvStypeMap()
                                                                        .get(channel)
                                                                        .getS_type_set();
    Set<Integer> s_type_group_set = MutableCaches.getInstance().Z_TAG_SNAPSHOT.getCacheContent()
                                                                              .getvStypeMap()
                                                                              .get(channel)
                                                                              .getS_type_group_set();
    if(CollectionUtils.isNotEmpty(this.type1s)){
      if(!s_type_group_set.containsAll(this.type1s))
        throw new InvalidParameterException("s_type_group is invalid for channel " + Constants.INVERSE_ChannelMap.get(channel));
    }
    if(CollectionUtils.isNotEmpty(this.type2s)){
      if(!s_type_set.containsAll(this.type2s)){
        throw new InvalidParameterException("s_type is invalid for channel " + Constants.INVERSE_ChannelMap.get(channel));
      }
    }
    return true;
  }

  public boolean isValidDestination(){
    if(StringUtils.isNotEmpty(this.destination) && StringUtils.isNotEmpty(this.destCountry)) {
      Map<String, List<String>> listMap = MutableCaches.getInstance().CITY_COUNTRY_MAP_ALL
        .getCacheContent();
      List<String> countryNames = listMap.get(this.destination);
      if(countryNames.contains(this.destCountry)){
        return true;
      }else {
        return false;
      }
    }
    return true;
  }

  //目的地转id
  /*public boolean format(){

  }*/

  public String getContinent() {
    return continent;
  }

  public void setContinent(String continent) {
    //System.out.println("setContinent " + continent);
    this.continent = continent;
  }

  public void setContinentIf(String dest){
    if(this.continent == null){
      this.continent = dest;
    }
  }

  public Set<Integer> getTopicids() {
    return topicids;
  }

  public void setTopicids(Set<Integer> topicids) {
    this.topicids = topicids;
  }

  public int getTravel_day() {
    return travel_day;
  }

  public void setTravel_day(int travel_day) {
    this.travel_day = travel_day;
  }

  public int getStart_city_id() {
    return start_city_id;
  }

  public void setStart_city_id(int start_city_id) {
    this.start_city_id = start_city_id;
  }

  public String getTopic() {
    return topic;
  }

  public void setTopic(String topic) {
    this.topic = topic;
  }

  public int getPoiid() {
    return poiid;
  }

  public void setPoiid(int poiid) {
    this.poiid = poiid;
  }

  public Map<String, Object> getAll_conditions() {
    return all_conditions;
  }

  public void setAll_conditions(Map<String, Object> all_conditions) {
    this.all_conditions = all_conditions;
  }

  public void reconstruct(String name){
    this.destination = name;
    this.userInputKW = null;
  }
  public void reconstructWithCity(String name){
    if(this.destination == null) {
      this.destination = name;
    }
  }

  public void reconstructWithCity2(String name){
    if(this.destination == null) {
      this.destination = name;
      this.userInputKW = null;
    }
  }

  public void reconstructWithCountry(String name){
    if(this.destCountry == null) {
      this.destCountry = name;
    }
  }

  public void reconstructWithCountry2(String name){
    if(this.destCountry == null) {
      this.destCountry = name;
      this.userInputKW = null;
    }
  }

  public List<SearchParameter> splitByType(int channel) throws Exception{
    //System.out.println("channel:"+channel);
    Map<Integer, List<Integer>> vMap = null;
    try {
      Map<Integer, ZTagEntity> vStypeMap = MutableCaches.getInstance().Z_TAG_SNAPSHOT.getCacheContent().getvStypeMap();
      //System.out.println("vStypeMap keySet:"+vStypeMap.keySet());
      if(vStypeMap.containsKey(channel)){
        //System.out.println("channel in");
      }else {
        //System.out.println(channel+"not in");
        return null;
      }
      vMap = MutableCaches.getInstance().Z_TAG_SNAPSHOT.getCacheContent().getvStypeMap()
                                                       .get(channel).getNegativeMap();
    }catch (Exception e){
      e.printStackTrace();
      System.out.println(e.toString());
      throw e;
    }
    List<SearchParameter> result = new ArrayList<>();
    HashSet<Integer> type1copy = new HashSet<>(type1s);

    if(CollectionUtils.isEmpty(type1s) && CollectionUtils.isEmpty(type2s)){
      result.add(makeSearchParameter(0, 0));

      //System.out.println("CollectionUtils.isEmpty(type1s) && CollectionUtils.isEmpty(type2s) size:"+result.size());
      return result;
    }

    for(int c : type2s){
      if(vMap.containsKey(c)) {
        List<Integer> p = vMap.get(c);
        int size = p.size();
        boolean isSelected = false;
        for(int i = 0; i < size; i++){
          int id = p.get(i);
          if (type1s.contains(id)) {
            result.add(makeSearchParameter(id, c));
            type1copy.remove(id);
            isSelected = true;
          }
        }
        if(!isSelected){
          result.add(makeSearchParameter(0, c));
        }
      }
    }

    for(int c1 : type1copy){

      result.add(makeSearchParameter(c1, 0));

    }
    if(result.size() == 0){
      throw new InvalidParameterException("context:"+context+",type1:"+type1+",type2:"+type2+",类目不存在，请检查后重新输入");
    }
    return result;
  }


  public List<SearchParameter> splitByType2(int channel) throws Exception{
    //System.out.println("channel:"+channel);
    Map<Integer, List<Integer>> vMap = null;
    try {
      Map<Integer, ZTagEntity> vStypeMap = MutableCaches.getInstance().Z_TAG_SNAPSHOT.getCacheContent().getvStypeMap();
      //System.out.println("vStypeMap keySet:"+vStypeMap.keySet());
      if(vStypeMap.containsKey(channel)){
        //System.out.println("channel in");
      }else {
        //System.out.println(channel+"not in");
        return null;
      }
      vMap = MutableCaches.getInstance().Z_TAG_SNAPSHOT.getCacheContent().getvStypeMap()
                                                       .get(channel).getNegativeMap();
    }catch (Exception e){
      e.printStackTrace();
      System.out.println(e.toString());
      throw e;
    }
    List<SearchParameter> result = new ArrayList<>();
    HashSet<Integer> type1copy = new HashSet<>(type1s);

    if(CollectionUtils.isEmpty(type1s) && CollectionUtils.isEmpty(type2s)){
      result.add(makeSearchParameter2(0, 0));

      //System.out.println("CollectionUtils.isEmpty(type1s) && CollectionUtils.isEmpty(type2s) size:"+result.size());
      return result;
    }

    for(int c : type2s){
      if(vMap.containsKey(c)) {
        List<Integer> p = vMap.get(c);
        int size = p.size();
        boolean isSelected = false;
        for(int i = 0; i < size; i++){
          int id = p.get(i);
          if (type1s.contains(id)) {
            result.add(makeSearchParameter2(id, c));
            type1copy.remove(id);
            isSelected = true;
          }
        }
        if(!isSelected){
          result.add(makeSearchParameter2(0, c));
        }
      }
    }

    for(int c1 : type1copy){

      result.add(makeSearchParameter2(c1, 0));

    }
    if(result.size() == 0){
      throw new InvalidParameterException("context:"+context+",type1:"+type1+",type2:"+type2+",类目不存在，请检查后重新输入");
    }
    return result;
  }



  public SearchParameter makeSearchParameter(int type1Int, int type2Int){
    return new SearchParameter(type1Int,type2Int,this.destinationCountryId, this.destinationCityId,
                               this.setOutPlaceId, this.supplierId, this.userInputKW, this.conditions,
                               this.context, this.requestId, this.user, this.pageInfo, this.destination,
                               this.destCountry, topicids, poiid, start_city_id, travel_day);
  }

  public SearchParameter makeSearchParameter2(int type1Int, int type2Int){
    return new SearchParameter(type1Int,type2Int,this.destinationCountryId, this.destinationCityId,
                               this.setOutPlaceId, this.supplierId, this.userInputKW, this.conditions,
                               this.context, this.requestId, this.user, this.pageInfo, this.destination,
                               this.destCountry, topicids, poiid, start_city_id, travel_day, continent);
  }

  public SearchParameter constructSearchParameter(int type1Int, int type2Int, String country){
    return new SearchParameter(type1Int,type2Int,this.destinationCountryId, this.destinationCityId,
                               this.setOutPlaceId, this.supplierId, this.userInputKW, this.conditions,
                               this.context, this.requestId, this.user, this.pageInfo, country);
  }
  public SearchParameter constructSearchParameterEx(int type1Int, int type2Int){
    String country = this.destCountry;
    if(destCountry == null) {
      country = MutableCaches.getInstance().CITY_COUNTRY_MAP.getCacheContent().get(destination);
    }
    if(country != null) {
      return new SearchParameter(type1Int, type2Int, this.destinationCountryId, this.destinationCityId,
                                 this.setOutPlaceId, this.supplierId, this.userInputKW, this.conditions,
                                 this.context, this.requestId, this.user, this.pageInfo, country);
    }else {
      return null;
    }
  }

  public List<SearchParameter> constructSearchParameterEx2(int type1Int, int type2Int){
    List<String> country = MutableCaches.getInstance().CITY_COUNTRY_MAP_LIST.getCacheContent().get(destination);
    int size = 0;
    if((country != null)) {
      size = country.size();
      List<SearchParameter> searchParameters = new ArrayList<>(size);
      for(int i = 0; i < size; i++) {
        searchParameters.add(
          new SearchParameter(type1Int, type2Int, this.destinationCountryId, this.destinationCityId,
                              this.setOutPlaceId, this.supplierId, this.userInputKW, this.conditions,
                              this.context, this.requestId, this.user, this.pageInfo, country.get(i)));
      }
      return searchParameters;
    }else {
      return null;
    }
  }

  public SearchParameter constructSearchParameterEx(int type1Int, int type2Int, String city){
    System.out.println("city:" + city);
    String country = MutableCaches.getInstance().CITY_COUNTRY_MAP.getCacheContent().get(city);
    System.out.println("country:" + country);
    if(country != null) {
      return new SearchParameter(type1Int, type2Int, this.destinationCountryId, this.destinationCityId,
                                 this.setOutPlaceId, this.supplierId, this.userInputKW, this.conditions,
                                 this.context, this.requestId, this.user, this.pageInfo, country);
    }else {
      return null;
    }
  }

  public List<SearchParameter> constructSearchParameterEx2(int type1Int, int type2Int, String city) {
    List<String> country = MutableCaches.getInstance().CITY_COUNTRY_MAP_LIST.getCacheContent().get(city);
    int size = 0;
    if((country != null)) {
      size = country.size();
      List<SearchParameter> searchParameters = new ArrayList<>(size);
      for(int i = 0; i < size; i++) {
        searchParameters.add(
          new SearchParameter(type1Int, type2Int, this.destinationCountryId, this.destinationCityId,
                              this.setOutPlaceId, this.supplierId, this.userInputKW, this.conditions,
                              this.context, this.requestId, this.user, this.pageInfo, country.get(i)));
      }
      return searchParameters;
    }else {
      return null;
    }
  }



  public List<SearchParameter> extendSearchParameter(int type1Int, int type2Int) {
    List<String> country = null;
    if(this.destCountry != null){
      country = new ArrayList<>(1);
      country.add(this.destCountry);
    }else {
      country = MutableCaches.getInstance().CITY_COUNTRY_MAP_LIST.getCacheContent()
                                                                 .get(this.destination);
    }
    int size = 0;
    if((country != null)) {
      size = country.size();
      //System.out.println("constructSearchParameterEx3 国家SIZE:"+size);
      List<SearchParameter> searchParameters = new ArrayList<>(size);
      for(int i = 0; i < size; i++) {
        searchParameters.add(
          new SearchParameter(type1Int,type2Int,this.destinationCountryId, this.destinationCityId,
                              this.setOutPlaceId, this.supplierId, this.userInputKW, this.conditions,
                              this.context, this.requestId, this.user, this.pageInfo, null,
                              country.get(i), topicids, poiid, start_city_id, travel_day));
      }
      return searchParameters;
    }else {
      return null;
    }
  }

  public List<SearchParameter> extendSearchParameterWithContinent(int type1Int, int type2Int) {
    List<String> country = null;
    if(this.destCountry != null){
      country = new ArrayList<>(1);
      country.add(this.destCountry);
    }else {
      country = MutableCaches.getInstance().CITY_COUNTRY_MAP_LIST.getCacheContent()
                                                                 .get(this.destination);
    }
    int size = 0;
    if((country != null)) {
      size = country.size();
      //System.out.println("constructSearchParameterEx3 国家SIZE:"+size);
      List<SearchParameter> searchParameters = new ArrayList<>(size);
      for(int i = 0; i < size; i++) {
        searchParameters.add(
          new SearchParameter(type1Int,type2Int,this.destinationCountryId, this.destinationCityId,
                              this.setOutPlaceId, this.supplierId, this.userInputKW, this.conditions,
                              this.context, this.requestId, this.user, this.pageInfo, null,
                              country.get(i), topicids, poiid, start_city_id, travel_day, this.continent));
      }
      return searchParameters;
    }else {
      return null;
    }
  }

  ////////////////////////新扩展
  public List<SearchParameter> extendSearchParameter(ExtendVType extendVType) {

    Set<Integer> set = extendVType.get_ST();
    List<String> country = null;
    if(this.destCountry != null){
      country = new ArrayList<>(1);
      country.add(this.destCountry);
    }else {
      country = MutableCaches.getInstance().CITY_COUNTRY_MAP_LIST.getCacheContent()
                                                                 .get(this.destination);
    }
    int size = 0;
    if((country != null)) {
      size = country.size();
      //System.out.println("constructSearchParameterEx3 国家SIZE:"+size);
      List<SearchParameter> searchParameters = new ArrayList<>(size);
      for(int i = 0; i < size; i++) {
        for(int stype:set) {
          searchParameters.add(new SearchParameter(0, stype, this.destinationCountryId,
                                                   this.destinationCityId, this.setOutPlaceId, this.supplierId, this.userInputKW,
                                                   this.conditions, this.context, this.requestId,
                                                   this.user, this.pageInfo, null, country.get(i),
                                                   topicids, poiid, start_city_id, travel_day));
        }
      }
      return searchParameters;
    }else {
      return null;
    }
  }

  public List<SearchParameter> extendSearchParameterWithContinent(ExtendVType extendVType) {

    Set<Integer> set = extendVType.get_ST();
    List<String> country = null;
    if(this.destCountry != null){
      country = new ArrayList<>(1);
      country.add(this.destCountry);
    }else {
      country = MutableCaches.getInstance().CITY_COUNTRY_MAP_LIST.getCacheContent()
                                                                 .get(this.destination);
    }
    int size = 0;
    if((country != null)) {
      size = country.size();
      //System.out.println("constructSearchParameterEx3 国家SIZE:"+size);
      List<SearchParameter> searchParameters = new ArrayList<>(size);
      for(int i = 0; i < size; i++) {
        for(int stype:set) {
          searchParameters.add(new SearchParameter(0, stype, this.destinationCountryId,
                                                   this.destinationCityId, this.setOutPlaceId, this.supplierId, this.userInputKW,
                                                   this.conditions, this.context, this.requestId,
                                                   this.user, this.pageInfo, null, country.get(i),
                                                   topicids, poiid, start_city_id, travel_day, continent));
        }
      }
      return searchParameters;
    }else {
      return null;
    }
  }
  ////////////////////////

  @JsonIgnore
  private boolean isNullParameter(){
    if(StringUtils.isBlank(type1) && StringUtils.isBlank(type2) && StringUtils.isBlank(userInputKW)
      && (destinationCountryId ==0) && (destinationCityId == 0) && (setOutPlaceId == -1)
      && (supplierId == 0) && (StringUtils.isBlank(this.destination)))
      return false;
    return true;
  }

  @JsonIgnore
  private boolean isNullParameter2(){
    if(StringUtils.isEmpty(this.type1) && StringUtils.isBlank(type2) && StringUtils.isBlank(userInputKW)
      && (destinationCountryId ==0) && (destinationCityId == 0) && (setOutPlaceId == -1)
      && (supplierId == 0) && (StringUtils.isBlank(this.destination)) && (StringUtils.isEmpty(
      this.destCountry)) && (StringUtils.isEmpty(this.continent)) && (StringUtils.isEmpty(this.topic))
      && (this.poiid == -1) && (this.start_city_id == -1) && (this.travel_day == -1))
      return false;
    return true;
  }

  public SearchParameter getTaiwanSP(int t1, int t2){
    return new SearchParameter(t1, t2, this.destinationCountryId, this.destinationCityId,
                               this.setOutPlaceId, this.supplierId, this.userInputKW, this.conditions,
                               this.context, this.requestId, this.user, this.pageInfo, "台湾", null);
  }

  public SearchParameter extendTaiwanSP(int t1, int t2){
    return new SearchParameter(t1,t2,this.destinationCountryId, this.destinationCityId,
                               this.setOutPlaceId, this.supplierId, this.userInputKW, this.conditions,
                               this.context, this.requestId, this.user, this.pageInfo, "台湾",
                               null, topicids, poiid, start_city_id, travel_day);

  }

  public SearchParameter extendTaiwanSPWithContinent(int t1, int t2){
    return new SearchParameter(t1,t2,this.destinationCountryId, this.destinationCityId,
                               this.setOutPlaceId, this.supplierId, this.userInputKW, this.conditions,
                               this.context, this.requestId, this.user, this.pageInfo, "台湾",
                               null, topicids, poiid, start_city_id, travel_day, continent);

  }
  ////新扩展
  public List<SearchParameter> extendTaiwanSPList(ExtendVType extendVType){
    List<SearchParameter> list = new ArrayList<>();
    Set<Integer> set = extendVType.get_ST();
    for(int stype:set){
      list.add(new SearchParameter(0,stype,this.destinationCountryId, this.destinationCityId,
                               this.setOutPlaceId, this.supplierId, this.userInputKW, this.conditions,
                               this.context, this.requestId, this.user, this.pageInfo, "台湾",
                               null, topicids, poiid, start_city_id, travel_day));
    }
    return list;
  }

  public List<SearchParameter> extendTaiwanSPListWithContinent(ExtendVType extendVType){
    List<SearchParameter> list = new ArrayList<>();
    Set<Integer> set = extendVType.get_ST();
    for(int stype:set){
      list.add(new SearchParameter(0,stype,this.destinationCountryId, this.destinationCityId,
                                   this.setOutPlaceId, this.supplierId, this.userInputKW, this.conditions,
                                   this.context, this.requestId, this.user, this.pageInfo, "台湾",
                                   null, topicids, poiid, start_city_id, travel_day, continent));
    }
    return list;
  }

  //new epoch
  @JsonIgnore
  public boolean isCountryAbsent(){
    return this.destCountry == null? true:false;
  }
  @JsonIgnore
  public boolean isCityAbsent(){
    return this.destination ==null? true:false;
  }

  public AggregationRegular getAggregationRegular(int channel){
    Map<Integer, List<Integer>> vMap = MutableCaches.getInstance().Z_TAG_SNAPSHOT.getCacheContent()
                                                                                 .getvStypeMap().get(channel).getNegativeMap();
    Map<Integer, List<Integer>> nevMap = MutableCaches.getInstance().Z_TAG_SNAPSHOT.getCacheContent()
                                                                                 .getvStypeMap().get(channel).getPositiveMap();

    Set<Integer> set = MutableCaches.getInstance().Z_TAG_SNAPSHOT.getCacheContent()
                                                                 .getvStypeMap().get(channel).getS_type_set();
    Set<Integer> set1 = MutableCaches.getInstance().Z_TAG_SNAPSHOT.getCacheContent()
                                                                  .getvStypeMap().get(channel).getS_type_group_set();
    Map<Integer, List<Integer>> STGFilter = MutableCaches.getInstance().Z_TAG_SNAPSHOT.getCacheContent().getvStypeMap().get(channel).getSTG_Filter();
    Map<Integer, List<Integer>> STFilter = MutableCaches.getInstance().Z_TAG_SNAPSHOT.getCacheContent().getvStypeMap().get(channel).getST_Filter();




    if(CollectionUtils.isEmpty(type1s) && CollectionUtils.isEmpty(type2s)){
      Map<Integer, Set<Integer>> tmp = new HashMap<>();
      Map<Integer, Set<Integer>> tmp1 = new HashMap<>();
      Map<Integer, Set<Integer>> tmp2 = new HashMap<>();
      for(int a:set1){
        if(STGFilter.containsKey(a)) {
          Set<Integer> set2 = new HashSet<>(STGFilter.get(a));
          tmp.put(a, set2);
        }
      }

      for(int a:set){
        if(STFilter.containsKey(a)) {
          Set<Integer> set2 = new HashSet<>(STFilter.get(a));
          tmp1.put(a, set2);
        }
      }

      Iterator<Map.Entry<Integer,List<Integer>>> iterator = nevMap.entrySet().iterator();
      while (iterator.hasNext()){
        Map.Entry<Integer,List<Integer>> entry = iterator.next();
        tmp2.put(entry.getKey(), new HashSet<Integer>(entry.getValue()));
      }

      AggregationRegular regular = new AggregationRegular(tmp2, tmp1, tmp, channel);
      if(!isCountryAbsent())
        regular.setCountry(this.destCountry);
      if(this.destination != null){
        regular.setCity(this.destination);
      }
      if(this.continent != null){
        regular.setContinent(this.continent);
      }
      return regular;
    }

    HashSet<Integer> type1copy = new HashSet<>(type1s);
    Map<Integer, Set<Integer>> stgFilter = new HashMap<>();
    Map<Integer, Set<Integer>> stFilter = new HashMap<>();
    Map<Integer, Set<Integer>> vTypeMap = new HashMap<>();

    for(int c : type2s){
      if(vMap.containsKey(c)) {
        List<Integer> p = vMap.get(c);
        int size = p.size();
        boolean isSelected = false;
        for(int i = 0; i < size; i++){
          int id = p.get(i);
          if (type1s.contains(id)) {
            if(vTypeMap.containsKey(id)){
              vTypeMap.get(id).add(c);
              if(STFilter.containsKey(c)) {
                stFilter.put(c, new HashSet<Integer>(STFilter.get(c)));
              }
            }else {
              Set<Integer> integerSet = new HashSet<>();
              integerSet.add(c);
              vTypeMap.put(id, integerSet);
              if(STFilter.containsKey(c)) {
                stFilter.put(c, new HashSet<Integer>(STFilter.get(c)));
              }
            }
            type1copy.remove(id);
            isSelected = true;
          }
        }
        if(!isSelected){
          List<Integer> list = vMap.get(c);
          if(CollectionUtils.isNotEmpty(list)){
            //
            for(int a:list){
              Set<Integer> integerSet = new HashSet<>();
              integerSet.add(c);
              vTypeMap.put(a, integerSet);
              if(STFilter.containsKey(c)) {
                stFilter.put(c, new HashSet<Integer>(STFilter.get(c)));
              }
            }
            //
          }
        }
      }
    }

    for(int c1 : type1copy){
      List<Integer> list = nevMap.get(c1);
      Set<Integer> integerSet = new HashSet<>(list);
      vTypeMap.put(c1, integerSet);
      if(STGFilter.containsKey(c1)){
        stgFilter.put(c1, new HashSet<Integer>(STGFilter.get(c1)));
      }
      for(int m:list){
        if(STFilter.containsKey(m)){
          stFilter.put(m, new HashSet<Integer>(STFilter.get(m)));
        }
      }
    }

    AggregationRegular regular = new AggregationRegular(vTypeMap, stFilter, stgFilter, channel);
    if(!isCountryAbsent())
      regular.setCountry(this.destCountry);
    if(this.destination != null){
      regular.setCity(this.destination);
    }
    //System.out.println("connnnnn:"+continent);
    if(this.continent != null)
      regular.setContinent(this.continent);
    return regular;

  }

  /////////////////////个性化是否启用/////////////////////
  public boolean isIndividuation(MarketingListInfo marketingListInfo){
    if(marketingListInfo == null)
      return false;
    int type = marketingListInfo.getType();
    int placeId = marketingListInfo.getPlaceId();
    if(type == 1){
      System.out.println("国家");
      System.out.println();
      String cn = MutableCaches.getInstance().INVERSE_COUNTRIES.getCacheContent().get(placeId);
      if(StringUtils.isEmpty(cn))
        return false;
      if(StringUtils.isNotEmpty(continent)){
        System.out.println("大洲不为空");
        String con = MutableCaches.getInstance().COUNTRY_CONTINENT_MAP.getCacheContent().get(cn);
        if(StringUtils.isEmpty(con))
          return false;
        if(!con.equals(continent))
          return false;
      }
      if(StringUtils.isNotEmpty(destCountry)){
        System.out.println("国家不为空");
        if(!destCountry.equals(cn))
          return false;
      }

      if(StringUtils.isNotEmpty(destination)){
        System.out.println("城市不为空");
        if(destinationCityId != 0){
          System.out.println("ca");
          int IdCountry = MutableCaches.getInstance().CITY_COUNTRY_ID_MAP.getCacheContent().get(destinationCityId);
          if(IdCountry != placeId)
            return false;
        }else {
          System.out.println("cb");
          int IdCity = MutableCaches.getInstance().CITIES.getCacheContent().get(destination);
          int IdCountry = MutableCaches.getInstance().CITY_COUNTRY_ID_MAP.getCacheContent().get(IdCity);
          if(IdCountry != placeId)
            return false;
        }
      }
      return true;
    }else {
      String cn = MutableCaches.getInstance().INVERSE_CITIES.getCacheContent().get(placeId);
      int countryId = MutableCaches.getInstance().CITY_COUNTRY_ID_MAP.getCacheContent().get(placeId);
      int continentId = MutableCaches.getInstance().COUNTRY_CONTINENT_ID_MAP.getCacheContent().get(countryId);

      if(StringUtils.isEmpty(continent) && StringUtils.isEmpty(destCountry) && StringUtils.isEmpty(destination))
        return true;
      if(StringUtils.isNotEmpty(continent)){
        if(MutableCaches.getInstance().CONTINENT_DICT.getCacheContent().getReverseDict().containsKey(continent)) {
          int conId = MutableCaches.getInstance().CONTINENT_DICT.getCacheContent().getReverseDict()
                                                                .get(continent);
          if(conId != continentId)
            return false;
        }
      }
      /////////////////////
      if(StringUtils.isNotEmpty(destCountry)){
        if(destinationCountryId!=0){
          if(destinationCountryId != countryId)
            return false;
        }else {
          int IdCountry = MutableCaches.getInstance().COUNTRIES.getCacheContent().get(destCountry);
          if(IdCountry != countryId)
            return false;
        }
      }

      ////////////////////////
      if(StringUtils.isNotEmpty(destination)){
        if(destinationCityId != 0){
          if(destinationCityId != placeId){
            return false;
          }
        }else {
          int IdCity = MutableCaches.getInstance().CITIES.getCacheContent().get(destination);
          if(IdCity != placeId)
            return false;
        }
      }

      return true;
    }
  }

  /////////////////////////////////////////////////////
  public MarketingListInfo getMarketListWithIndividuation(PreferKey preferKey, MarketingInfoForPlace marketingInfoForPlace){
    MarketingListInfo marketingListInfo = null;
    long t = System.currentTimeMillis();
    //
    Map<String, Integer> cityInfo = MutableCaches.getInstance().CITIES.getCacheContent();
    Map<String, Integer> countryInfo = MutableCaches.getInstance().COUNTRIES.getCacheContent();
    Map<String, Integer> continentInfo = MutableCaches.getInstance().CONTINENT_DICT.getCacheContent().getReverseDict();

    //目的地精确到城市
    if(StringUtils.isNotEmpty(this.destination) || this.destinationCityId > 0){
      if(StringUtils.isNotEmpty(this.destination) && this.destinationCityId <= 0){
        if(cityInfo.containsKey(destination)) {
          this.destinationCityId = cityInfo.get(destination);
        }
      }
      if(this.destinationCityId > 0){
        //////////////////////////////
        marketingListInfo = marketingInfoForPlace.getCityMarketListInfo(destinationCityId);
        if(marketingListInfo.isEmpty())
          marketingListInfo = null;
        return marketingListInfo;
        //////////////////////////////
      }
    }
    //目的地精确到国家
    if(StringUtils.isNotEmpty(this.destCountry) || this.destinationCountryId > 0){
      if(StringUtils.isNotEmpty(this.destCountry) && this.destinationCountryId <= 0){
        if(countryInfo.containsKey(destCountry))
          this.destinationCountryId = countryInfo.get(destCountry);
      }
      if(this.destinationCountryId > 0){
        marketingListInfo = marketingInfoForPlace.getCountryMLInfo(destinationCountryId);
        if(marketingListInfo.isEmpty())
          marketingListInfo = null;
        return marketingListInfo;
      }
    }
    //目的地精确到大洲
    if(StringUtils.isNotEmpty(this.continent)){
      int continentId = 0;
      if(continentInfo.containsKey(this.continent))
        continentId = MutableCaches.getInstance().CONTINENT_DICT.getCacheContent().getReverseDict().get(continent);
      if(continentId > 0){
        marketingListInfo = marketingInfoForPlace.getContinentMLInfo(continentId);
        if(marketingListInfo.isEmpty())
          marketingListInfo = null;
        return marketingListInfo;
      }

    }
    //目的地未指定
    //用户身份不明
    if(preferKey == null){
      return marketingListInfo;
    }
    //用户身份可确定
    try {
      PreferDestination preferDestination = PreferCache.getCache(preferKey);
      marketingListInfo = marketingInfoForPlace.getMLInfoWithUserPrefer(preferDestination);
    }catch (Exception e){
      e.printStackTrace();
    }
    return marketingListInfo;
  }
  /////////////////////////////////////////////////////

  //////////////////////
  public boolean isIndividuationByUI(){
    MarketingInfoForPlace marketingInfoForPlace = MutableCaches.getInstance().MARKET_INFO.getCacheContent();
    if(StringUtils.isNotEmpty(destination)){

    }
    return false;
  }
}
